home *** CD-ROM | disk | FTP | other *** search
- #include <btree.h>
- #include <ingres.h>
- #include <opsys.h>
- #include <sccs.h>
-
- SCCSID(@(#)btree_util.c 8.3 5/30/88)
-
- /* Trace up to the root of the BTree, incrementing (or decrementing) all
- ** key values.
- **
- ** Parameters :
- ** tree - BTree filename (I)
- ** block - starting node from which path is traced (I)
- ** inc - either +1 or -1 (I)
- */
-
- tracepath(rootpage, block, inc)
-
- long rootpage;
- register struct locator *block;
- register int inc;
- {
- struct locator p, child;
-
- if (block->pageno != rootpage) /* if at root, no need for adjustment */
- {
- bmove(block, &child, sizeof(struct locator));
-
- /* trace up to root node */
- do
- {
- p.pageno = child.page.parent;
- parentkey(child.pageno, &p);
- p.page.node.intnode.key[p.offset] += inc;
- write_node(p.pageno, &p.page);
- bmove(&p, &child, sizeof(struct locator));
- } while (p.pageno != rootpage);
- }
- }
-
- /* Determines which key/ptr pair is the parent of the given page
- **
- ** Parameters :
- ** tree - BTree filename (I)
- ** block - page number of child (I)
- ** prt - information about the parent of the child (I, O)
- **
- */
-
- parentkey(block, prt)
-
- long block;
- register struct locator *prt;
- {
- register int i;
-
- get_node(prt->pageno, &prt->page);
- /* find pointer in parent which references desired block */
- for (i = 0; prt->page.node.intnode.ptr[i] != block && i < prt->page.nelmts; ++i)
- continue;
-
- if (i == prt->page.nelmts)
- syserr("parentkey: child = %ld", block);
- prt->offset = i;
- return(0);
- }
-
- /* Retrieve a node from the BTree
- **
- ** Parameters :
- ** tree - BTree filename (I)
- ** pagenum - page number of page to be retrieved (I)
- ** buffer - buffer into which page is retrieved (O)
- */
-
- get_node(pagenum, buffer)
-
- long pagenum;
- register struct BTreeNode *buffer;
- {
- extern int Btree_fd;
-
- if ( lseek(Btree_fd, pagenum * PGSIZE, 0) == -1 )
- syserr("GET_NODE: seek to %ld failed",pagenum);
- if (read(Btree_fd, buffer, sizeof *buffer) != sizeof *buffer)
- syserr("GET_NODE: read btree, page %ld", pagenum);
- }
-
- /* Write a node into the BTree file name
- **
- ** Parameters :
- ** tree - BTree filename (I)
- ** pagenum - page number of page to be written (I)
- ** buffer - buffer containing page to be written (I)
- */
-
- write_node(pagenum, buffer)
-
- long pagenum;
- register struct BTreeNode *buffer;
- {
- extern int Btree_fd;
-
- lseek(Btree_fd, pagenum * PGSIZE, 0);
- if (write(Btree_fd, buffer, PGSIZE) != PGSIZE)
- syserr("WRITE_NODE: write btree, page %ld", pagenum);
- }
-
- /* Retrieves a new page from the BTree file. If there is an empty page
- ** in the file, that page is used. Otherwise, a new page is added to
- ** the end of the file.
- **
- ** Parameters :
- ** tree - BTree filename (I)
- **
- ** Returns :
- ** page number of new page
- */
-
- long
- new_page(tree)
-
- char *tree;
- {
- int i;
- long freepage, newpage;
- struct BTreeNode page, root, garbage;
- struct stat fileinfo;
- extern DESC Btreesec;
-
- get_node(RT, &root);
- freepage = root.parent;
- if (freepage == 0)
- /* no free pages in file, add a new page to the end */
- {
- /* determine page number of page at very end of file */
- stat(tree, &fileinfo);
- newpage = fileinfo.st_size / PGSIZE;
- write_node(newpage, &page);
- }
- else
- /* use first free page, adjusting free page chain */
- {
- newpage = freepage;
- get_node(newpage, &garbage);
- root.parent = garbage.parent;
- write_node(RT, &root);
- }
- return(newpage);
- }
-
- /* Returns an empty file to the empty file list. The head of the list
- ** is indicated through the parent of the root and linked together
- ** through the parents of the empty pages.
- **
- ** Parameters :
- ** tree - BTree filename (I)
- ** pagenum - page number of empty page (I)
- */
-
- return_page(pagenum)
-
- long pagenum;
- {
- struct BTreeNode root, freepage;
-
- /* indicate that page is free by inserting its page number at the
- ** head of the free page list */
- get_node(RT, &root);
- get_node(pagenum, &freepage);
- freepage.parent = root.parent;
- freepage.depth = 0;
- write_node(pagenum, &freepage);
- root.parent = pagenum;
- write_node(RT, &root);
- }
-
- /*
- ** Determine the lid that corresponds to a given position in the B-Tree.
- **
- ** Parameters :
- ** tree - BTree name (I)
- ** tidloc - location in BTree (I)
- **
- ** Returns :
- ** lid value
- */
- get_lid(tidloc, lid)
-
- TID *tidloc;
- long lid[];
- {
- static struct locator tid;
- register int i, j;
- long l, child;
-
- do
- {
- /* determine where in BTree to search */
- pluck_page(tidloc, &tid.pageno);
-
- get_node(tid.pageno, (char *) &tid.page);
- tid.offset = tid.page.node.leafnode.back_ptr[tidloc->line_id & I1MASK];
-
- if (tid.offset > tid.page.nelmts - 1)
- syserr("get_lid: bad tid location %ld, tid.offset=%d, tid.page.nelmts=%d", *tidloc, tid.offset,tid.page.nelmts);
-
- /* scan through leaf */
- for (l = 1, i = tid.offset; i > 0; ++l, --i)
- continue;
- /* trace up to root, adding keys */
- while (!tid.page.depth)
- {
- child = tid.pageno;
- tid.pageno = tid.page.parent;
- parentkey(child, &tid);
- for (i = tid.offset - 1; i >= 0; l += tid.page.node.intnode.key[i--])
- continue;
- }
- lid[tid.page.depth - 1] = l;
- # ifdef xATR1
- if (tTf(24,0))
- printf("lid=%ld\n", lid[tid.page.depth - 1]);
- # endif
- bmove(&tid.page.prttree, tidloc, LIDSIZE);
- } while (tid.page.depth > 1);
- }
-
- /*
- ** Uses the secondary btree relation to find the btree tid corresponding
- ** to a given main relation tid
- */
-
- search_btree(mtid, tidloc)
-
- TID mtid;
- register TID *tidloc;
- {
- char key[2 * LIDSIZE], tup[2 * LIDSIZE];
- TID tid;
- extern DESC Btreesec;
-
- # ifdef xATR1
- if (tTf(24,0))
- {
- printf("In Search_btree: searching for tid %ld\n", mtid);
- printdesc(&Btreesec);
- }
- # endif
- clearkeys(&Btreesec);
- setkey(&Btreesec, key, &mtid, 1);
- if (!getequal(&Btreesec, key, tup, &tid))
- bmove(tup + LIDSIZE, tidloc, LIDSIZE);
- else
- syserr("search_btree:can't find mtid %ld in btree", mtid);
- # ifdef xATR1
- if (tTf(24,0))
- printup(&Btreesec, tup);
- # endif
- }
-
- /*
- ** Linearly searches the leaves of the BTree for a desired tid
- **
- ** Parameters :
- ** tree - BTree file name (I)
- ** tid - desired tid value (I)
- ** tidloc - location of the desired tid (O)
- */
-
- lin_search(level, tid, tidloc, lid, tupcnt)
-
- int level;
- long tid;
- TID *tidloc;
- long lid[];
- long tupcnt;
- {
- struct locator block;
- register int i;
- long page, t, next;
- int found;
- long nextpage, count;
- int forward, first;
-
- page = RT;
- for (i = 0; i < level - 1; ++i)
- {
- t = get_tid(page, lid[i], &block);
- page = t;
- }
-
- found = 0;
- forward = 0;
- first = 1;
- do
- {
- if (!forward)
- {
- get_node(page, &block.page);
- next = block.page.nexttree;
- }
- count = 0;
-
- /* start at leftmost leaf */
- do
- {
- get_node(page, &block.page);
- if (forward)
- nextpage = block.page.nexttree;
- else
- nextpage = block.page.prevtree;
- get_tid(page, 1, &block);
- for ( ; ; )
- {
- /* search through leaf */
- for (i = 0; i < block.page.nelmts && block.page.node.leafnode.tid_pos[block.page.node.leafnode.tid_loc[i]] != tid; ++i)
- {
- if (!first)
- ++count;
- }
- if (i < block.page.nelmts && block.page.node.leafnode.tid_pos[block.page.node.leafnode.tid_loc[i]] == tid)
- {
- found = 1;
- break; /* tid found */
- }
- first = 0;
- if (!(block.pageno = block.page.node.leafnode.nextleaf) || count >= tupcnt)
- break; /* all leaves exhausted */
- else
- /* try leaf to the right */
- get_node(block.pageno, &block.page);
- }
- if (found || count >= tupcnt)
- break;
- } while (page = nextpage);
- nextpage = next;
- forward = !forward;
- } while (forward != 0 && !found);
- if (!found)
- syserr("search_btree: tid not found %ld", tid);
- else
- {
- stuff_page(tidloc, &block.pageno);
- tidloc->line_id = block.page.node.leafnode.tid_loc[i];
- }
- }
-
- /*
- ** Determines the value corresponding to the very last lid in the
- ** BTree.
- **
- ** Parameters :
- ** tree - BTree file name (I)
- **
- ** Returns :
- ** value of last lid
- */
- long
- last_lid(rootpage)
-
- long rootpage;
-
- {
- register int i;
- long lid;
- struct BTreeNode root;
-
- lid = 0;
- get_node(rootpage, &root);
- if (root.nodetype == 'L')
- lid = root.nelmts;
- else
- for (i = 0; i < root.nelmts; ++i)
- lid += root.node.intnode.key[i];
- ++lid;
- return(lid);
- }
-
- /*
- ** Changes the tid value stored in the leaf of a BTree node
- **
- ** Parameters :
- ** tree - BTree file name (I)
- ** tid - new tid value (I)
- ** tidloc - location of tid to be replaced (I)
- */
-
- replace_btree(tid, tidloc)
-
- long tid;
- register TID *tidloc;
-
- {
- long pageno;
- struct BTreeNode p;
-
- pluck_page(tidloc, &pageno);
- get_node(pageno, &p);
- p.node.leafnode.tid_pos[tidloc->line_id] = tid;
- write_node(pageno, &p);
- }
-